package com.brt.museum.service.auth.impl;

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.ContinueLoop;
import org.nutz.lang.Each;
import org.nutz.lang.ExitLoop;
import org.nutz.lang.Lang;
import org.nutz.lang.LoopException;

import com.brt.museum.bean.auth.Permission;
import com.brt.museum.bean.auth.Role;
import com.brt.museum.bean.auth.User;
import com.brt.museum.service.auth.IPermissionService;
import com.brt.museum.service.auth.IRoleService;
import com.brt.museum.service.auth.IShiroUserService;
import com.brt.museum.service.auth.IUserService;
import com.brt.museum.vo.MenuNode;
import com.dgj.utils.collection.Lists;
import com.dgj.utils.entries.Result;

@IocBean
public class ShiroUserService implements IShiroUserService {

	@Inject
	IUserService userService;
	@Inject
	IRoleService roleService;
	@Inject
	IPermissionService permissionService;

	@Override
	public User findByName(String userName) {
		return userService.findByName(userName);
	}

	@Override
	public List<Permission> getAllPermissions(int id) {
		List<Permission> permissions = getDirectPermissions(id);
		permissions.addAll(getIndirectPermissions(id));
		return Lists.removeDuplicateWithOrder(permissions);
	}

	@Override
	public List<String> getAllPermissionsInfo(int id) {
		List<Permission> permissions = getAllPermissions(id);
		final List<String> target = Lists.newArrayList();
		Lang.each(permissions, new Each<Permission>() {

			@Override
			public void invoke(int index, Permission ele, int length) throws ExitLoop, ContinueLoop, LoopException {
				target.add(ele.getName());
			}
		});
		return target;
	}

	@Override
	public List<Role> getAllRoles(int id) {
		// XXX 直接权限即全部权限
		return getDirectRoles(id);
	}

	@Override
	public List<Permission> getDirectPermissions(int id) {
		return permissionService.findByUserId(id);
	}

	@Override
	public List<Role> getDirectRoles(int id) {
		return roleService.findByUserId(id);
	}

	@Override
	public List<Permission> getIndirectPermissions(int id) {
		List<Role> roles = getAllRoles(id);
		return permissionService.findByRoles(roles);
	}

	@Override
	public boolean checkPermission(String permission, int id) {
		return Arrays.binarySearch(Lang.collection2array(getAllPermissions(id)), permission) > 1;
	}

	@Override
	public boolean checkRole(String role, int id) {
		return Arrays.binarySearch(Lang.collection2array(getAllRoles(id)), role) > 1;
	}

	@Override
	public List<Role> getIndirectRoles(int id) {
		return Lists.newArrayList();
	}

	@Override
	public List<String> getRolesInfo(int id) {
		final List<String> roles = Lists.newArrayList();
		Lang.each(getAllRoles(id), new Each<Role>() {

			@Override
			public void invoke(int index, Role ele, int length) throws ExitLoop, ContinueLoop, LoopException {
				roles.add(ele.getName());
			}
		});
		return roles;
	}

	@Override
	public Result login(String userName, String password) {
		try {
			User user = findByName(userName);
			if (user == null) {
				return Result.fail("用户名或密码不存在");
			}
			if (!user.isAvailable()) {
				return Result.fail("账户被锁定");
			}
			Subject currentUser = SecurityUtils.getSubject();
			UsernamePasswordToken token = new UsernamePasswordToken(userName, password);
			token.setRememberMe(true);
			currentUser.login(token);
			return Result.success().addData("loginUser", user);
		} catch (LockedAccountException e) {
			return Result.fail("账户被锁定");
		} catch (Exception e) {
			e.printStackTrace();
			return Result.fail("登录失败");
		}
	}

	@Override
	public List<Permission> getMenuPermissions(int id) {
		List<Permission> permissions = getAllPermissions(id);
		final List<Permission> target = Lists.newArrayList();
		Lang.each(permissions, new Each<Permission>() {

			@Override
			public void invoke(int index, Permission ele, int length) throws ExitLoop, ContinueLoop, LoopException {
				if (ele.isMenu()) {
					target.add(ele);
				}
			}
		});
		return target;
	}

	@Override
	public List<MenuNode> getMenu(int id) {
		/**
		 * 1.获取全部菜单权限<br>
		 * 2.按照group进行分组
		 */
		List<Permission> permissions = getMenuPermissions(id);
		final List<MenuNode> target = Lists.newArrayList();

		Lang.each(permissions, new Each<Permission>() {

			@Override
			public void invoke(int index, Permission permission, int length) throws ExitLoop, ContinueLoop, LoopException {
				/**
				 * 从目标组中获取当前权限的分组名称,如果有就拿出来把当前权限往里面放,如果没有就创建一个往里面放
				 */
				MenuNode node = getNode(target, permission);
				if (node != null) {
					node.getPermissions().add(permission);
				} else {
					node = new MenuNode();
					node.setGroup(permission.getMenuGroup());
					List<Permission> ps = Lists.newArrayList();
					ps.add(permission);
					node.setPermissions(ps);
					target.add(node);
				}
				Collections.sort(node.getPermissions(), new Comparator<Permission>() {

					@Override
					public int compare(Permission p1, Permission p2) {
						return p1.getId() - p2.getId();
					}
				});
			}
		});
		return target;
	}

	/**
	 * 获取当前权限所属的组
	 * 
	 * @param target
	 * @param permission
	 * @return
	 */
	protected MenuNode getNode(List<MenuNode> target, Permission permission) {
		for (MenuNode node : target) {
			if (node.getGroup() == permission.getMenuGroup()) {
				return node;
			}
		}
		return null;
	}
}
